-
Notifications
You must be signed in to change notification settings - Fork 481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8176270: Adding ChangeListener to TextField.selectedTextProperty causes StringOutOfBoundsException #73
Conversation
Hi koppor, welcome to this OpenJDK project and thanks for contributing! We do not recognize you as Contributor and need to ensure you have signed the Oracle Contributor Agreement (OCA). If you have not signed the OCA, please follow the instructions. Please fill in your GitHub username in the "Username" field of the application. Once you have signed the OCA, please let us know by writing If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please use "Add GitHub user koppor" as summary for the issue. If you are contributing this work on behalf of your employer and your employer has signed the OCA, please let us know by writing |
/signed |
Thank you! Please allow for up to two weeks to process your OCA, although it is usually done within one to two business days. Also, please note that pull requests that are pending an OCA check will not usually be evaluated, so your patience is appreciated! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left comments inline. This will need changes. Also, you will need to provide a test that fails without the fix and passes with the fix.
if (end > start + length) end = length; | ||
if (start > length-1) start = end = 0; | ||
// Ensure that the last character to get is within the bounds of the txt string | ||
if (end >= start + length) end = length-1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, I think the existing test is simply wrong: Why should the start
value matter when checking whether the end
value needs to be clamped -- it's an end
point not a number of characters. I think the entire problem might be the fact that it is comparing against start + length
. Second, the value to be clamped to was correct before your change. The substring
method to which end
is passed is documented as subtracting 1.
I think the test should be something like:
if (end > length) end = length;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on second thought: correct clamping or not, the start/end indices of selection are invalid whenever text was removed/added at an index before the selection - they are in coordinates of the old text, not the new. If they point to an index > new textLength, incorrect clamping will throw. If they are both < new textLength, it'll fire an intermediate changeEvent with incorrect selection, the total sequence beining
oldSelectedText -> incorrectly-shifted-selectedText
incorrectly-shifted-selectedText -> empty
The correct change notification would be, because at the end of the text change, the selection is cleared,
oldSelectedText -> empty
To me, it looks like using a binding here is not the best of options.
// Ensure that the last character to get is within the bounds of the txt string | ||
if (end >= start + length) end = length-1; | ||
// In case the start is after the whole txt, nothing valid is selected. Thus, return the default. | ||
if (start >= length) return ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change seems OK, and might be clearer than the existing code, but the existing code is correct, and produces the same effect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, it is correct - but while we are changing the impl, we might go the whole way and clean up :) my pref would be to add the check for start to the short-circuit at the beginning of the method, something like
String txt = text.get();
IndexRange sel = selection.get();
if (txt == null || sel == null || sel.getStart() >= text.getLength()) return "";
}); | ||
textField.positionCaret(5); | ||
Semaphore semaphore = new Semaphore(0); | ||
Platform.runLater(semaphore::release); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since controls tests run using the StubToolkit, Platform.runLater
does not do what you expect. If you need to run a pulse to get some code to run that normally would run as part of pulse, you can call that method directly. See other controls tests for how this is done.
Just a comment on how to add a failing test: we can replace the actual typing (in the TestFx context) by programmatically replacing the selection, actually, it doesn't even need the skin (so no scene nor parent) because all collaborators are in TextInputControl:
Similarly, an invalidationListener that access the selectedText throws, while an invalidationListener not accessing the selected is fine. To make the error show up on the test thread, replace the uncaughtExceptionHandler before (and cleanup after):
|
/reviewers 2 |
@kevinrushforth |
@koppor are you planning to resume work on this PR? |
Closing, since there has been no activity for 3 months. @koppor - if you would like to pursue this, please address the pending feedback and reopen the PR. |
This is a WIP PR. Requesting for comments.
I could not replicate the test given at https://bugs.openjdk.java.net/browse/JDK-8176270 without TestFX. I nevertheless let my try to replicate the @test things in here.
The fix is just a wild guess without really understanding the side effects of
.addListener
.Progress
Issue
Download
$ git fetch https://git.openjdk.java.net/jfx pull/73/head:pull/73
$ git checkout pull/73